﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Postnuclear.Dependency.Tree;
using Postnuclear.Test.Helpers;

namespace Postnuclear.Test.Dependency.Tree
  {
  /// <summary>
  /// Represents a test class for the <see cref="EventAdapter{THolder}"/> class.
  /// </summary>
  [TestClass]
  public sealed class EventAdapterTest
    : TestClassBase
    {
    #region Public

    // Methods

    /// <summary>
    /// Initializes this instance.
    /// </summary>
    [TestInitialize]
    public void Initialize()
      {
      Target = new Mock<IValueProvider<object>>();
      DependencyElement = new EventAdapter<IValueProvider<object>>(typeof(IValueProvider<object>).GetProperty("Value"));
      DependencyElement.UpdateHolderValue(Target.Object);
      }

    /// <summary>
    /// A test for <see cref="EventAdapter{THolder}"/> constructor to check exception for null event info.
    /// </summary>
    [TestMethod]
    [ExpectedException(typeof(ArgumentNullException))]
    public void CreateWithNullEventTest()
      {
      new EventAdapter<IValueProvider<object>>(null);
      }

    /// <summary>
    /// A test for <see cref="EventAdapter{THolder}"/> constructor to check exception for incorrect holder type.
    /// </summary>
    [TestMethod]
    [ExpectedException(typeof(ArgumentException))]
    public void CreateWithIncorrectHolderTypeTest()
      {
      new EventAdapter<EventAdapterTest>(Target.Object.GetType().GetEvent("ValueChanged"));
      }

    /// <summary>
    /// A test for <see cref="INotifyValueChanged.ValueChanged" /> event.
    /// </summary>
    [TestMethod]
    public void ValueChangedTest()
      {
      int updatesCount = 0;
      EventHandler<EventArgs> updateHandler = (_, __) => ++updatesCount;

      DependencyElement.ValueChanged += updateHandler;
      Assert.AreEqual(0, updatesCount);

      Target.RaiseValueChanged();
      Assert.AreEqual(1, updatesCount);

      Target.RaiseValueChanged();
      Assert.AreEqual(2, updatesCount);

      Target.RaiseValueChanged();
      Assert.AreEqual(3, updatesCount);

      DependencyElement.ValueChanged -= updateHandler;
      Assert.AreEqual(3, updatesCount);

      Target.RaiseValueChanged();
      Assert.AreEqual(3, updatesCount);
      }

    #endregion

    #region Private

    // Properties

    private Mock<IValueProvider<object>> Target
      {
      get;
      set;
      }

    private EventAdapter<IValueProvider<object>> DependencyElement
      {
      get;
      set;
      }

    #endregion
    }
  }
